﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace Edge.OAuth
{
    public class OAuth1
    {
        public const string SING_METHOD = "HMAC-SHA1";
        public const string OAUTH_VERSION = "1.0";

        public const string TIMESTAMP_PARAM = "oauth_timestamp";
        public const string OAUTH_NONCE_PARAM = "oauth_nonce";
        public const string SIGN_METHOD_PARAM = "oauth_signature_method";
        public const string OAUTH_VERSION_PARAM = "oauth_version";
        public const string OAUTH_CONSUMER_KEY_PARAM = "oauth_consumer_key";
        public const string OAUTH_SIGN_PARAM = "oauth_signature";
        public const string OAUTH_CALLBACK_PARAM = "oauth_callback";

        public const string OAUTH_AUTH_TOKEN_PARAM = "oauth_token";
        public const string OAUTH_AUTH_TOKEN_SECRET_PARAM = "oauth_token_secret";
        public const string OAUTH_CALLBACK_CONFIRMED_PARAM = "oauth_callback_confirmed";
        public const string OAUTH_VERIFIER_PARAM = "oauth_verifier";

        public OAuth1()
        {
        }

        public OAuth1(string ConsumerKey, string ConsumerSecret, string CallbackUrl)
        {
            _ConsumerKey = ConsumerKey;
            _ConsumerSecret = ConsumerSecret;
            _CallbackUrl = CallbackUrl;
        }

        public OAuth1(string ConsumerKey, string ConsumerSecret, string CallbackUrl, string Token, string TokenSecret,
                     string Verifier)
            : this(ConsumerKey, ConsumerSecret, CallbackUrl)
        {
            _Token = Token;
            _TokenSecret = TokenSecret;
            _Verifier = Verifier;
        }

        private int _TimeDelta = 0;

        public int TimeDelta
        {
            get { return _TimeDelta; }
            set { _TimeDelta = value; }
        }

        private string _ConsumerKey = string.Empty;

        public string ConsumerKey
        {
            get { return _ConsumerKey; }
            set { _ConsumerKey = value; }
        }

        private string _ConsumerSecret = string.Empty;

        public string ConsumerSecret
        {
            get { return _ConsumerSecret; }
            set { _ConsumerSecret = value; }
        }

        private string _CallbackUrl = string.Empty;

        public string CallbaclUrl
        {
            get { return _CallbackUrl; }
            set { _CallbackUrl = value; }
        }

        private string _Token = string.Empty;

        public string Token
        {
            get { return _Token; }
            set { _Token = value; }
        }

        private string _TokenSecret = string.Empty;

        public string TokenSecret
        {
            get { return _TokenSecret; }
            set { _TokenSecret = value; }
        }

        private string _Verifier = string.Empty;

        public string Verifier
        {
            get { return _Verifier; }
            set { _Verifier = value; }
        }
        public Dictionary<string, string> GetRequestToken(string request_url, Dictionary<string, string> addiotionalParameters, AuthType atype)
        {
            string timestamp = OAuthCommonUtils.GetTimestamp(_TimeDelta);
            string nonce = OAuthCommonUtils.GetNonce();

            Dictionary<string, string> items = new Dictionary<string, string>();

            items.Add(OAUTH_CONSUMER_KEY_PARAM, _ConsumerKey);
            items.Add(OAUTH_NONCE_PARAM, nonce);
            items.Add(OAUTH_VERSION_PARAM, OAUTH_VERSION);
            items.Add(SIGN_METHOD_PARAM, SING_METHOD);
            items.Add(TIMESTAMP_PARAM, timestamp);
            items.Add(OAUTH_CALLBACK_PARAM, OAuthCommonUtils.UrlEncode(_CallbackUrl));

            if (addiotionalParameters != null)
                foreach (var item in addiotionalParameters)
                    items.Add(item.Key, OAuthCommonUtils.UrlEncode(item.Value));

            string basesign = OAuthCommonUtils.GetBasesign("GET",
                                            request_url,
                                            items);
            string sign = OAuthCommonUtils.GetHMACSHA1(_ConsumerSecret, _TokenSecret,
                            basesign);
            items[OAUTH_CALLBACK_PARAM] = _CallbackUrl;

            items.Add(OAUTH_SIGN_PARAM, sign);
            if (addiotionalParameters != null)
                foreach (var item in addiotionalParameters)
                    items[item.Key] = item.Value;
            string p = string.Empty;
            string header = string.Empty;
            if (atype == AuthType.AuthHeader)
            {
                header = OAuthCommonUtils.GetAuthHeader(items);
                if (addiotionalParameters != null)
                    p = OAuthCommonUtils.GetParametersString(addiotionalParameters);
            }
            else
                p = OAuthCommonUtils.GetParametersString(items);
            Dictionary<string, string> dict = OAuthCommonUtils.SendGetRequest(request_url + p, true, header);
            try //надо добавить проверку на наличие ключей в словаре
            {
                _Token = dict[OAUTH_AUTH_TOKEN_PARAM];
                _TokenSecret = dict[OAUTH_AUTH_TOKEN_SECRET_PARAM];
            }
            catch (Exception)
            { //если по ключам ничего нет - ошибка получения маркера
            }
            return dict;
        }
        public void GoToAuth(string oauthorize_url, string oauth_token, Dictionary<string, string> additionalParemeters)
        {
            string p = string.Empty;
            if (additionalParemeters != null)
                p = string.Join("&", additionalParemeters.Select(x => string.Format("{0}={1}", x.Key, OAuthCommonUtils.UrlEncode(x.Value))) as string[]);
            HttpContext.Current.Response.Redirect(string.Format("{0}?{2}={1}{3}", oauthorize_url, oauth_token, OAUTH_AUTH_TOKEN_PARAM, !string.IsNullOrEmpty(p) ? "&" + p : ""), false);
        }
        public enum AuthType
        {
            UrlParams,
            AuthHeader
        }
        public Dictionary<string, string> GetAccessToken(string access_url, AuthType atype)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            dict.Add(OAUTH_VERIFIER_PARAM, OAuthCommonUtils.UrlEncode(_Verifier));
            dict.Add(OAUTH_AUTH_TOKEN_PARAM, OAuthCommonUtils.UrlEncode(_Token));

            string timestamp = OAuthCommonUtils.GetTimestamp(_TimeDelta);
            string nonce = OAuthCommonUtils.GetNonce();

            dict.Add(OAUTH_CONSUMER_KEY_PARAM, _ConsumerKey);
            dict.Add(OAUTH_NONCE_PARAM, nonce);
            dict.Add(OAUTH_VERSION_PARAM, OAUTH_VERSION);
            dict.Add(SIGN_METHOD_PARAM, SING_METHOD);
            dict.Add(TIMESTAMP_PARAM, timestamp);

            string basesign = OAuthCommonUtils.GetBasesign("GET",
                                        access_url,
                                        dict);
            string sign = OAuthCommonUtils.GetHMACSHA1(_ConsumerSecret, _TokenSecret,
                        basesign);

            string authorization = string.Empty;

            dict.Add(OAUTH_SIGN_PARAM, sign);
            dict[OAUTH_AUTH_TOKEN_PARAM] = _Token;
            dict[OAUTH_VERIFIER_PARAM] = _Verifier;
            if (atype == AuthType.AuthHeader)
            {
                authorization = OAuthCommonUtils.GetAuthHeader(dict);
            }
            Dictionary<string, string> result = null;

            result = OAuthCommonUtils.SendGetRequest(access_url + (atype != AuthType.AuthHeader ? OAuthCommonUtils.GetParametersString(dict) : ""), true, authorization);
            try
            {
                _Token = result[OAUTH_AUTH_TOKEN_PARAM];
                _TokenSecret = result[OAUTH_AUTH_TOKEN_SECRET_PARAM];
            }
            catch (Exception) { }
            return result;
        }
    }

   
}
